/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_httpd.htm
 *
 * Zhiqim Httpd is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.httpd.nio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;

/**
 * HTTP连接信息类，包括输入输出流，实现Runnable，用于线程处理
 *
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 */
public final class HttpNioSslConnection extends HttpNioConnection
{
    private SSLEngine sslEngine;
    private HttpNioSslBuffer buffer;
    
    public HttpNioSslConnection(HttpNioSslListener listener, SocketChannel channel, String remoteAddr, int remotePort, SSLEngine sslEngine)
    {//HTTPS
        super(listener, channel, remoteAddr, remotePort);
        
        this.sslEngine = sslEngine;
        this.buffer = new HttpNioSslBuffer(sslEngine);
    }
    
    public SSLEngine getSSLEngine()
    {
        return sslEngine;
    }
    
    /****************************************************************************/
    //SSL读数据握手&关闭
    /****************************************************************************/
    
    @Override /** 关闭后置，SSL连接重写 */
    protected void closeAfter()
    {
        if (sslEngine != null)
        {//关闭SSL引擎
            sslEngine.closeOutbound();
            try{sslEngine.closeInbound();}catch (SSLException e){}
            sslEngine = null;
        }
    }
    
    /*******************************************************************************************/
    //重写方法，1）读包后解包处理，2）写入数据方法并封包处理，3）关联websocket
    /*******************************************************************************************/
    
    @Override /** 判断消息头，SSL连接可重写 */
    protected void chkHeader()
    {
        if (header == null || header.isParsed())
            header = new HttpNioHeader(this, sslEngine);
    }
    
    @Override /** 解决缓冲数据，SSL连接可重写 */
    protected int parseBuffer()
    {
        return buffer.parseBuffer(netBuf, header.getInputStream());
    }
    
    @Override /** 写入数据并封包处理 */
    public void write(byte[] data, int off, int len) throws IOException
    {
        ByteBuffer appBuf = ByteBuffer.wrap(data);
        ByteBuffer netBuf = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize());
        while (appBuf.hasRemaining())
        {
            netBuf.clear();
            sslEngine.wrap(appBuf, netBuf);
            netBuf.flip();
            
            //写入到通道
            super.write(netBuf);
        }
    }
    
    @Override
    public String toString()
    {
        return new StringBuilder("HttpNioSslConnection[").append(connId).append("]").toString();
    }
}
